﻿using Microsoft.Practices.ServiceLocation;
using SimpleInjector;
using SimpleInjector.Extensions;

namespace Beaker.Injection.Desktop.SimpleInjector
{
	/// <summary>
	/// Injection Provider for Simple Injector
	/// </summary>
	public sealed class SimpleInjectorInjectionProvider
		: IInjectionProvider
	{
		/// <summary>
		/// Create a new container builder.
		/// </summary>
		/// <returns>The newly container builder.</returns>
		public IContainerBuilder CreateContainerBuilder()
		{
			return new ContainerBuilder();
		}

		/// <summary>
		/// Register the provider service locator with the provider
		/// </summary>
		/// <param name="builder">The builder to regsiter the service locator with.</param>
		/// <param name="locator">The service locator to register with the builder.</param>
		public void RegisterServiceLocator(IContainerBuilder builder, IServiceLocator locator)
		{
			((ContainerBuilder)builder).RegisterServiceLocator(locator);
		}

		/// <summary>
		/// Register the factory interface with the builder
		/// </summary>
		/// <param name="builder">The builder to register the factory interface with.</param>
		public void RegisterFactory(IContainerBuilder builder)
		{
			((Container)builder.PhysicalContainer).RegisterOpenGeneric(typeof(IFactory<>), typeof(Factory<>));
		}

		/// <summary>
		/// Builder the final query container and lock it so no alterations are possible anymore.
		/// </summary>
		/// <param name="builder">The builder that has all the registration to apply to the container.</param>
		/// <param name="skipVerify">Set to skip verification</param>
		/// <returns>The created query container.</returns>
		public IQueryContainer BuildAndLock(IContainerBuilder builder, bool skipVerify)
		{
			var containerBuilder = (ContainerBuilder)builder;
			var container = (Container)containerBuilder.PhysicalContainer;

			// and let the deferred registrations to register all at once.
			containerBuilder.RegisterDeferredRegistrations();

			// register container on container, so you can inject the IQueryContainer if required.
			var queryContainer = new QueryContainer(container);
			container.RegisterSingle<IQueryContainer>(queryContainer);

			if (!skipVerify)
				container.Verify();

			return queryContainer;
		}
	}

}
